/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.navid.trafalgar.model.opengl2;

import com.navid.trafalgar.model.GameModel;
import com.jme3.asset.AssetManager;
import com.jme3.light.AmbientLight;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.post.Filter;
import com.jme3.post.filters.DepthOfFieldFilter;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.texture.Texture;
import com.jme3.texture.Texture2D;
import com.jme3.util.SkyFactory;
import com.navid.trafalgar.definition.Entry;
import com.navid.trafalgar.definition.GameDefinition;
import com.navid.trafalgar.definition.HarnessDefinition;
import com.navid.trafalgar.definition.MaterialDefinition;
import com.navid.trafalgar.definition.MillestoneDefinition;
import com.navid.trafalgar.definition.ShipDefinition;
import com.navid.trafalgar.definition.TextureDefinition;
import com.navid.trafalgar.model.AHarnessModel;
import com.navid.trafalgar.model.AMillestoneModel;
import com.navid.trafalgar.model.AShipModel;
import com.navid.trafalgar.model.AShipOneModel;
import com.navid.trafalgar.model.AShipZeroModel;
import com.navid.trafalgar.model.ASimpleWater;
import com.navid.trafalgar.model.IModelBuilder;
import com.navid.trafalgar.model.SimpleContext;
import com.navid.trafalgar.model.SunModel;
import java.util.Collection;

/**
 *
 * @author alberto
 */
public class ModelBuilder implements IModelBuilder {

    AssetManager assetManager;

    public ModelBuilder(AssetManager assetManager) {
        this.assetManager = assetManager;
    }
    
    private Texture buildTexture(TextureDefinition textureDefinition){
        return assetManager.loadTexture(textureDefinition.getTextureName());
    }
    
    private Material buildMaterial(MaterialDefinition materialDefinition){
        Material mat = new Material(assetManager, materialDefinition.getName());
        
        for(Entry<String, TextureDefinition> currentTexture : materialDefinition.getTextures() ){
            mat.setTexture(currentTexture.getKey(), buildTexture(currentTexture.getValue()));
        }
        
        for(Entry<String, int[]> currentTexture : materialDefinition.getColors() ){
            mat.setColor(currentTexture.getKey(), new ColorRGBA(currentTexture.getValue()[0], currentTexture.getValue()[1], currentTexture.getValue()[2] ,currentTexture.getValue()[3]));
        }
        
        return mat;
    }

    public AShipModel buildShip(ShipDefinition shipDefinition) {

        AShipZeroModel shipModel = new ShipZeroModel(assetManager);

        shipModel.move(new Vector3f(shipDefinition.getPosition()[0], shipDefinition.getPosition()[1], shipDefinition.getPosition()[2]));
        shipModel.setHullMaterial(buildMaterial(shipDefinition.getHullMaterial()));
        shipModel.setSailMaterial(buildMaterial(shipDefinition.getSailMaterial()));
        
        return shipModel;
    }
    
    public AShipModel buildGhostShip(ShipDefinition shipDefinition) {

        AShipZeroModel shipModel = new ShipZeroModel(assetManager);

        shipModel.move(new Vector3f(shipDefinition.getPosition()[0], shipDefinition.getPosition()[1], shipDefinition.getPosition()[2]));
        Material ghostMaterial = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
        ghostMaterial.setColor("ColorMap", ColorRGBA.Black);
        shipModel.setHullMaterial(ghostMaterial);
        shipModel.setSailMaterial(ghostMaterial);
        shipModel.setTransparent(true);
        return shipModel;
    }

    public MillestoneModel buildMillestone(MillestoneDefinition millestoneDefinition) {

        MillestoneModel millestoneModel = new MillestoneModel(assetManager);
        
        millestoneModel.setMaterialOff(buildMaterial(millestoneDefinition.getMaterialOff()));
        millestoneModel.setMaterialOn(buildMaterial(millestoneDefinition.getMaterialOn()));

        millestoneModel.setLocalTranslation(new Vector3f(millestoneDefinition.getPosition()[0], millestoneDefinition.getPosition()[1], millestoneDefinition.getPosition()[2]));

        return millestoneModel;
    }
    
    public HarnessModel buildHarness(HarnessDefinition definition, AShipModel target){
        
        HarnessModel harnessModel = new HarnessModel(assetManager);
        
        harnessModel.setTarget(target);
        
        return harnessModel;
    }

    
    
    private SimpleWater buildWater(Node rootNode, Vector3f lightDir, Collection<Filter> filterCollection) {
        SimpleWater simpleWater = new SimpleWater(rootNode, lightDir, filterCollection);
        simpleWater.setWaterTexture((Texture2D) assetManager.loadTexture("Common/MatDefs/Water/Textures/foam2.jpg"));

        return simpleWater;
    }

    public GameModel buildGameModel(GameDefinition gameDef) {
        GameModel gameModel = new GameModel();
        
        Node gameNode = new Node("reflexion");
        gameModel.setGameNode(gameNode);
        
        //Wind
        SimpleContext simpleContext = new SimpleContext();
        gameModel.setiContext(simpleContext);
        if(gameDef.getWind() !=null){
            RotateSimpleWind wind = new RotateSimpleWind(assetManager);
            wind.setWind(gameDef.getWind().getVector2f());
            simpleContext.setWind(wind);
        }

        //Ship
        for (java.util.Map.Entry<String, ShipDefinition> shipDefEntry : gameDef.getShips().entrySet()) {
            AShipModel shipModel = buildShip(shipDefEntry.getValue());
            gameModel.getShips().put(shipDefEntry.getKey(), shipModel);
            shipModel.setContext(simpleContext);
            gameNode.attachChild(shipModel);
        }

        //Millestones
        for (java.util.Map.Entry<String, MillestoneDefinition> millestoneDef : gameDef.getMillestones().entrySet()) {
            AMillestoneModel millestoneModel = buildMillestone(millestoneDef.getValue());
            gameModel.getMillestones().put(millestoneDef.getKey(), millestoneModel);
            gameNode.attachChild(millestoneModel);
        }

        //Sky
        if (gameDef.getSky() != null) {
            Spatial sky = SkyFactory.createSky(assetManager, gameDef.getSky().getSkyTexture(), gameDef.getSky().isSpheric());
            sky.setLocalScale(gameDef.getSky().getScale());
            gameModel.setSky(sky);
            gameNode.attachChild(sky);
        }

       //Sun
        if(gameDef.getSun() !=null){
            SunModel sunModel = new SunModel(gameDef.getSun().getVector3f(), gameDef.getSun().getColorRGBA());
            gameModel.setSun(sunModel);
            gameNode.addLight(sunModel);
        }
        //Extra light;
        gameNode.addLight(new AmbientLight());
        
        //Water
        if(gameDef.getWater() != null && gameDef.getWater().isExists()){
        ASimpleWater simpleWater = buildWater(gameNode, gameDef.getSun().getVector3f(), gameModel.getFpp());
        gameNode.attachChild(simpleWater);
        }
        
        if(gameDef.getHarness() != null){
            AHarnessModel harness =buildHarness(gameDef.getHarness(), gameModel.getShips().get(gameDef.getHarness().getShipName()));
            gameModel.setHarness(harness);
            gameNode.attachChild(harness);
        }

       /* LightScatteringFilter lsf = new LightScatteringFilter(gameModel.getSun().);
        lsf.setLightDensity(1.0f);
        gameModel.getFpp().add(lsf);*/

        DepthOfFieldFilter dof = new DepthOfFieldFilter();
        dof.setFocusDistance(0);
        dof.setFocusRange(100);
        gameModel.getFpp().add(dof);
        
        
        return gameModel;
    }

    public AShipModel buildGhost(GameDefinition game) {
return buildGhostShip(game.getShips().get("ship1"));    
    
    }
}
